home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / go32 / event.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-04  |  8.5 KB  |  302 lines

  1. /**
  2.  ** EVENT.C
  3.  **
  4.  **  Copyright (C) 1992, Csaba Biegl
  5.  **    820 Stirrup Dr, Nashville, TN, 37221
  6.  **    csaba@vuse.vanderbilt.edu
  7.  **
  8.  **  This file is distributed under the terms listed in the document
  9.  **  "copying.cb", available from the author at the address above.
  10.  **  A copy of "copying.cb" should accompany this file; if not, a copy
  11.  **  should be available from where this file was obtained.  This file
  12.  **  may not be distributed without a verbatim copy of "copying.cb".
  13.  **  You should also have received a copy of the GNU General Public
  14.  **  License along with this program (it is in the file "copying");
  15.  **  if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  16.  **  Cambridge, MA 02139, USA.
  17.  **
  18.  **  This program is distributed in the hope that it will be useful,
  19.  **  but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.  **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.  **  GNU General Public License for more details.
  22.  **/
  23.  
  24. #ifndef  __TURBOC__
  25. #error     Don't even try to compile it with this compiler
  26. #endif
  27.  
  28. #pragma  inline
  29.  
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <alloc.h>
  33. #include <stdio.h>
  34. #include <time.h>
  35. #include <dos.h>
  36.  
  37. #include "eventque.h"
  38.  
  39. extern int  far _ev_interss;    /* interrupt stack segment */
  40. extern int  far _ev_interds;    /* interrupt data segment */
  41. extern int  far _ev_kbintsp;    /* keyboard interrupt stack */
  42. extern int  far _ev_msintsp;    /* mouse interrupt stack */
  43. extern int  far _ev_kbinter;    /* keyboard interrupt flag */
  44. extern int  ctrl_c_flag;
  45.  
  46. extern void interrupt (* far _ev_oldkbint)(void);
  47.  
  48. extern void far          _ev_mouseint(void);
  49. extern void interrupt _ev_keybdint(void);
  50.  
  51. static void dummydraw(void) {}
  52.  
  53. static EventQueue *queue = NULL;
  54. static void (*mousedraw)(void) = dummydraw;
  55. static char *stack = NULL;
  56. static char *qsave = NULL;
  57.  
  58. static int  ms_xpos;
  59. static int  ms_ypos;
  60. static int  ms_xmickey;
  61. static int  ms_ymickey;
  62.  
  63. #ifdef FOR_GO32
  64. #ifndef  USE_AT_BIOS        /* always use AT BIOS calls for GO32 version */
  65. #define  USE_AT_BIOS
  66. #endif
  67. #else
  68. static int  first_call = 1;
  69. #endif
  70.  
  71. #define MS_ENABLE   EVENT_ENABLE(EVENT_MOUSE)
  72. #define KB_ENABLE   EVENT_ENABLE(EVENT_KEYBD)
  73.  
  74. #define KB_SSIZE    128        /* keyboard handler stack size */
  75. #define MS_SSIZE    128        /* mouse handler MINIMAL stack size */
  76.  
  77. #define IABS(x)        (((x) > 0) ? (x) : -(x))
  78.  
  79. /* This is an ARDI hack to fit all the bits showing both right and left
  80.  * shift, control, and alt keys (from both normal and extended keyboards)
  81.  * into a single byte.  This format is only set if EVENT_RAWKEY events are 
  82.  * chosen.  See eventque.h for the KB_RAW flags for testing these states.
  83.  */
  84.  
  85. static unsigned char
  86. fetch_kb_flags (void)
  87. {
  88.     unsigned short flags;
  89.  
  90. #ifdef USE_AT_BIOS
  91.     _AX = 0x1200;
  92. #else
  93.     _AX = 0x200;
  94. #endif
  95.     geninterrupt(0x16);
  96.     flags = _AX;
  97.     if (!(queue->evq_enable & EVENT_ENABLE (EVENT_RAWKEY)))
  98.         return flags;
  99.     else
  100.         return ((flags & 3) << 4) | ((flags >> 8) & 0xCF);
  101.     /* This returns extended flags replacing scroll/num locks with shifts */
  102. }
  103.  
  104. void far _ev_mousehandler(int msk,int btn,int mx,int my)
  105. {
  106.     EventRecord *ep;
  107.     int moved = 0;
  108.     int diff;
  109.  
  110.     if((diff = mx - ms_xmickey) != 0) {
  111.         ms_xmickey += diff;
  112.         ms_xpos    += diff;
  113.         if((diff = ms_xpos / queue->evq_xspeed) != 0) {
  114.         ms_xpos %= queue->evq_xspeed;
  115.         if(IABS(diff) >= queue->evq_thresh) diff *= queue->evq_accel;
  116.         diff += queue->evq_xpos;
  117.         if(diff <= queue->evq_xmin) diff = queue->evq_xmin;
  118.         if(diff >= queue->evq_xmax) diff = queue->evq_xmax;
  119.         if(diff != queue->evq_xpos) {
  120.             queue->evq_xpos  = diff;
  121.             queue->evq_moved = moved = 1;
  122.         }
  123.         }
  124.     }
  125.     if((diff = my - ms_ymickey) != 0) {
  126.         ms_ymickey += diff;
  127.         ms_ypos    += diff;
  128.         if((diff = ms_ypos / queue->evq_yspeed) != 0) {
  129.         ms_ypos %= queue->evq_yspeed;
  130.         if(IABS(diff) >= queue->evq_thresh) diff *= queue->evq_accel;
  131.         diff += queue->evq_ypos;
  132.         if(diff <= queue->evq_ymin) diff = queue->evq_ymin;
  133.         if(diff >= queue->evq_ymax) diff = queue->evq_ymax;
  134.         if(diff != queue->evq_ypos) {
  135.             queue->evq_ypos  = diff;
  136.             queue->evq_moved = moved = 1;
  137.         }
  138.         }
  139.     }
  140.     if((msk & ~1) && (queue->evq_enable & MS_ENABLE)) {
  141.         disable();
  142.         ep = &queue->evq_events[queue->evq_wrptr];
  143.         if(++queue->evq_wrptr == queue->evq_maxsize)
  144.         queue->evq_wrptr = 0;
  145.         if(queue->evq_cursize < queue->evq_maxsize)
  146.         queue->evq_cursize++;
  147.         else if(++queue->evq_rdptr == queue->evq_maxsize)
  148.         queue->evq_rdptr = 0;
  149.         enable();
  150.         ep->evt_kbstat = fetch_kb_flags();
  151.         ep->evt_type   = EVENT_MOUSE;
  152.         ep->evt_mask   = msk;
  153.         ep->evt_button = btn;
  154.         ep->evt_xpos   = queue->evq_xpos;
  155.         ep->evt_ypos   = queue->evq_ypos;
  156.         ep->evt_time   = clock();
  157.     }
  158.     if(moved && queue->evq_drawmouse) (*mousedraw)();
  159. }
  160.  
  161. void far _ev_keybdhandler(void)
  162. {
  163.     EventRecord *ep;
  164.     int keycode,scancode;
  165.  
  166.     /* This section ARDI mods merged by C. Sandmann */
  167.     if (queue->evq_enable & EVENT_ENABLE (EVENT_RAWKEY)) {
  168.         /* Fetch raw scancode from the keyboard.
  169.            Assume 0 means nothing there. */
  170.         scancode = inportb (0x60) << 8;
  171.         if (scancode != 0) {
  172.         /* Queue up the event. */
  173.         disable ();
  174.         ep = &queue->evq_events[queue->evq_wrptr];
  175.         if(++queue->evq_wrptr == queue->evq_maxsize)
  176.             queue->evq_wrptr = 0;
  177.         if(queue->evq_cursize < queue->evq_maxsize)
  178.             queue->evq_cursize++;
  179.         else if(++queue->evq_rdptr == queue->evq_maxsize)
  180.             queue->evq_rdptr = 0;
  181.         enable();
  182.         ep->evt_kbstat   = fetch_kb_flags ();
  183.         ep->evt_keycode  = 0;
  184.         ep->evt_scancode = scancode;
  185.         ep->evt_type     = EVENT_RAWKEY;
  186.         ep->evt_time     = clock();
  187.         }
  188.     }
  189.  
  190.     if(queue->evq_enable & KB_ENABLE) for( ; ; ) {
  191. #ifdef USE_AT_BIOS
  192.         _AX = 0x1100;
  193. #else
  194.         _AX = 0x100;
  195. #endif
  196.         geninterrupt(0x16);
  197.         asm jnz  charpresent;
  198.         return;
  199.       charpresent:
  200.         scancode = _AX;
  201.         if(scancode == 0)ctrl_c_flag = 1;
  202.         keycode  = (_AL == 0) ? _AH + 0x100 :
  203. #ifdef USE_AT_BIOS
  204.         (_AL == 0xe0) ? _AH + 0x200 :
  205. #endif
  206.         _AL;
  207.         if(queue->evq_delchar) {
  208. #ifdef USE_AT_BIOS
  209.         _AX = 0x1000;
  210. #else
  211.         _AX = 0;
  212. #endif
  213.         geninterrupt(0x16);
  214.         }
  215.         disable();
  216.         ep = &queue->evq_events[queue->evq_wrptr];
  217.         if(++queue->evq_wrptr == queue->evq_maxsize)
  218.         queue->evq_wrptr = 0;
  219.         if(queue->evq_cursize < queue->evq_maxsize)
  220.         queue->evq_cursize++;
  221.         else if(++queue->evq_rdptr == queue->evq_maxsize)
  222.         queue->evq_rdptr = 0;
  223.         enable();
  224.         ep->evt_kbstat   = fetch_kb_flags();
  225.         ep->evt_keycode  = keycode;
  226.         ep->evt_scancode = scancode;
  227.         ep->evt_type     = EVENT_KEYBD;
  228.         ep->evt_time     = clock();
  229.     }
  230. }
  231.  
  232. void EventQueueDeInit(void)
  233. {
  234.     if(stack != NULL) {
  235.         _AX = 0;
  236.         geninterrupt(0x33);
  237. #ifdef FOR_GO32
  238.         _ev_kbinter = 1;
  239. #else
  240.         setvect(9,_ev_oldkbint);
  241. #endif
  242.         free(stack);
  243.         free(qsave);
  244.         stack = NULL;
  245.     }
  246. }
  247.  
  248. EventQueue *EventQueueInit(int qsize,int ms_stksize,void (*msdraw)(void))
  249. {
  250.     if(stack != NULL) EventQueueDeInit();
  251.     if(qsize < 20) qsize = 20;
  252.     if(ms_stksize < MS_SSIZE) ms_stksize = MS_SSIZE;
  253.     stack = malloc(KB_SSIZE + ms_stksize);
  254.     qsave = malloc(sizeof(EventQueue)+(sizeof(EventRecord)*(qsize-1))+4);
  255.     if((stack == NULL) || (qsave == NULL)) {
  256.         if(stack != NULL) { free(stack); stack = NULL; }
  257.         if(qsave != NULL) { free(qsave); qsave = NULL; }
  258.         return(NULL);
  259.     }
  260.     _ev_interds = FP_SEG(&ms_xpos);
  261.     _ev_interss = FP_SEG(stack);
  262.     _ev_kbintsp = FP_OFF(stack) + KB_SSIZE;
  263.     _ev_msintsp = FP_OFF(stack) + KB_SSIZE + ms_stksize;
  264.     ms_xpos = ms_xmickey = 0;
  265.     ms_ypos = ms_ymickey = 0;
  266.     queue = (EventQueue *)(((long)qsave + 3L) & ~3L);
  267.     memset(queue,0,sizeof(EventQueue));
  268.     queue->evq_maxsize   = qsize;
  269.     queue->evq_xmax         = 79;
  270.     queue->evq_ymax         = 24;
  271.     queue->evq_xspeed    = 8;
  272.     queue->evq_yspeed    = 16;
  273.     queue->evq_thresh    = 100;
  274.     queue->evq_accel     = 1;
  275.     queue->evq_delchar   = 1;
  276.     queue->evq_enable    = MS_ENABLE | KB_ENABLE;
  277.     _AX = 0;
  278.     geninterrupt(0x33);
  279.     if(_AX != 0) {
  280.         _AX = 11;
  281.         geninterrupt(0x33);
  282.         mousedraw = (msdraw != NULL) ? msdraw : dummydraw;
  283.         _ES = FP_SEG(_ev_mouseint);
  284.         _DX = FP_OFF(_ev_mouseint);
  285.         _CX = 0xff;
  286.         _AX = 0x0c;
  287.         geninterrupt(0x33);
  288.     } else                    /* so mouse requiring progs */
  289.         queue->evq_enable &= ~MS_ENABLE;    /* can die gracefully */
  290. #ifndef FOR_GO32
  291.     _ev_oldkbint = getvect(9);
  292.     setvect(9,_ev_keybdint);
  293.     if(first_call) {
  294.         atexit(EventQueueDeInit);
  295.         first_call = 0;
  296.     }
  297. #endif
  298.     _ev_kbinter = (-1);
  299.     return(queue);
  300. }
  301.  
  302.